﻿/************************************************************************

   Extended Silverlight Toolkit

   Copyright (C) 2010-2012 Xceed Software Inc.

   This program is provided to you under the terms of the Microsoft Public
   License (Ms-PL) as published at http://extendedsilverlight.codeplex.com/license

   Please purchase a commercial version of this toolkit if you are using
   it in a commercial product. The commercial versions support the project,
   and also include more features for each control, priority support,
   source code, updates, removed watermark, and a proprietary license.

   Visit http://xceed.com and follow @datagrid on Twitter.

  **********************************************************************/

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using Xceed.Silverlight.Data.Stats;

namespace Xceed.Silverlight.Data
{
  internal abstract class ListDataItemIndexNode
  {
    #region Constructor

    protected ListDataItemIndexNode( 
      ListDataItemIndexConfiguration configuration, 
      IEqualityComparer<StatFunction> statFunctionComparer,
      int level, 
      int indexStart, 
      int length )
    {
      if( configuration == null )
        throw new ArgumentNullException( "configuration" );

      if( statFunctionComparer == null )
        throw new ArgumentNullException( "statFunctionComparer" );

      if( level < 0 || level >= configuration.GroupValueComparers.Count )
        throw new ArgumentOutOfRangeException( "level" );

      this.SetIndexStart( indexStart );
      this.SetLength( length );
      this.ItemComparer = configuration.GroupValueComparers[ level ];

      m_statResults = new Dictionary<StatFunction, StatResult>( statFunctionComparer );
    }

    #endregion

    #region ItemComparer Property

    protected IComparer ItemComparer
    {
      get;
      private set;
    }

    #endregion

    #region IndexStart Property

    internal int IndexStart
    {
      get;
      private set;
    }

    protected void SetIndexStart( int value )
    {
      if( value < 0 )
        throw new ArgumentOutOfRangeException( "value", "value must be greater than or equal to zero." );

      this.IndexStart = value;
    }

    #endregion

    #region Length Property

    internal int Length
    {
      get;
      private set;
    }

    protected void SetLength( int value )
    {
      if( value <= 0 )
        throw new ArgumentOutOfRangeException( "value", "value must be greater than zero." );

      this.Length = value;
    }

    #endregion

    #region [ StatFunction ] Property

    internal StatResult this[ StatFunction statFunction ]
    {
      get
      {
        if( statFunction != null )
        {
          StatResult result;
          if( m_statResults.TryGetValue( statFunction, out result ) )
            return result;
        }

        return null;
      }
      set
      {
        if( statFunction != null )
        {
          m_statResults.Remove( statFunction );

          if( value != null )
          {
            m_statResults.Add( statFunction, value );
          }
        }
      }
    }

    #endregion

    internal virtual void ClearStatResults()
    {
      m_statResults.Clear();
    }

    internal virtual StatResult GetStatValue(
      StatFunction statFunction,
      LinkedListNode<object> groupValue )
    {
      if( groupValue != null )
        return null;

      return this[ statFunction ];
    }

    internal virtual void SetStatValue(
      StatFunction statFunction,
      LinkedListNode<object> groupValue,
      StatResult statResult )
    {
      if( groupValue == null )
      {
        this[ statFunction ] = statResult;
      }
    }

    internal virtual void SlideLeft()
    {
      this.SetIndexStart( this.IndexStart - 1 );
    }

    internal virtual void SlideRight()
    {
      this.SetIndexStart( this.IndexStart + 1 );
    }

    internal void Grow()
    {
      this.SetLength( this.Length + 1 );
    }

    internal void Shrink()
    {
      this.SetLength( this.Length - 1 );
    }

    internal abstract void Add( LinkedListNode<object> groupValue );
    internal abstract bool Remove( int index );

    internal abstract int GetDataItemIndex( LinkedListNode<object> groupValue, bool reverseOrder, bool skipStartingItem );

    internal abstract bool GetGroupCount( LinkedListNode<int> groupCount );
    internal abstract bool GetGroupCount( LinkedListNode<int> groupCount, LinkedListNode<object> groupValue );
    internal abstract bool GetGroupCount( LinkedListNode<int> groupCount, LinkedListNode<object> groupValue, bool reverseOrder, bool skipStartingItem );
    internal abstract bool GetGroupCount( LinkedListNode<int> groupCount, LinkedListNode<object> filterGroupValue, LinkedListNode<object> groupValue, bool reverseOrder, bool skipStartingItem );

    #region Private Fields

    private Dictionary<StatFunction, StatResult> m_statResults;

    #endregion
  }
}
